<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title> ARK OPTIONS MAKER</title>
    <style>
        html,
        body {
            margin: 0;
            padding: 0;
            width: 100%;
            height: 100%;
            background-color: #f0f0f0;
        }

        body {
            display: flex;
            align-items: center;
            justify-content: center;
            flex-direction: column;
        }

        #app {
            display: grid;
            width: 100%;
            max-width: 1080px;
            align-items: center;
            height: 560px;
            grid-template-rows: 56px 1fr auto;
            background-color: #fff;
            padding: 2em;
            box-shadow: 0px 8px 16px -8px rgba(0 0 0 / .25);
            gap: 1em;
        }

        header {
            width: 100%;
            position: sticky;
            display: flex;
            justify-content: center;
            align-items: center;
            height: 56px;
        }

        header>h1 {
            font-size: 1.6em;
            padding: 0;
            margin: 0;
        }

        #app>.selector {
            width: 100%;
            display: grid;
        }

        #app>.actions,
        #app>.commander {
            width: 100%;
            display: flex;
        }

        #app>.selector {
            grid-template-columns: repeat(3, auto);
            gap: .5em 1em;
        }

        #app>.actions {
            gap: 1em;
        }

        button {
            padding: .6em .8em;
            font-weight: bold;
            color: #333;
            background-color: rgba(0 0 0 / .06);
            border: none;
            border-radius: .25em;
        }

        button:disabled {
            opacity: .8;
        }

        button:hover {
            background-color: rgba(0 0 0 / .12);
        }

        button:active {
            background-color: rgba(0 0 0 / .2);
        }

        button:focus-visible {
            outline: solid 2px rgba(0 0 0 / .5);
        }

        #app>.commander {
            flex-direction: column;
        }
    </style>
</head>

<body>
    <div id="app">
        <header>
            <h1>AKK OPTIONS GENERATOR</h1>
        </header>
        <div class="selector"></div>
        <div class="actions">
            <button type="button" class="select-all">SELECT ALL</button>
            <button type="button" class="inverse">INVERSE</button>
            <button type="button" class="reset">RESET</button>
        </div>
        <div class="commander">
            <textarea placeholder="command" class="command"></textarea>
        </div>
    </div>
    <script>
        const SET_PARAM_COMMAND = 'hdc shell param set persist.ark.properties ';
        const DEFAULT_ARK_OPTIONS = 0x105cn;
        let arkOptions = DEFAULT_ARK_OPTIONS;
        let full64 = BigInt((1n << 65n) - 1n);
        console.info(full64)
        const TEXT_OPTIONS = `DEFAULT = -1, // default value 000'0000'0001'0000'0101'1100 -> 0x105c
    OPTIONAL_LOG = 1,
    GC_STATS_PRINT = 1 << 1,
    PARALLEL_GC = 1 << 2, // default enable
    CONCURRENT_MARK = 1 << 3, // default enable
    CONCURRENT_SWEEP = 1 << 4, // default enable
    THREAD_CHECK = 1 << 5,
    ENABLE_ARKTOOLS = 1 << 6, // default enable
    ENABLE_SNAPSHOT_SERIALIZE = 1 << 7,
    ENABLE_SNAPSHOT_DESERIALIZE = 1 << 8,
    EXCEPTION_BACKTRACE = 1 << 9,
    GLOBAL_OBJECT_LEAK_CHECK = 1 << 10,
    GLOBAL_PRIMITIVE_LEAK_CHECK = 1 << 11,
    ENABLE_IDLE_GC = 1 << 12, // default enable
    CPU_PROFILER_COLD_START_MAIN_THREAD = 1 << 13,
    ENABLE_CPU_PROFILER_VM_TAG = 1 << 14,
    ENABLE_GC_TRACER = 1 << 15,
    CPU_PROFILER_COLD_START_WORKER_THREAD = 1 << 16,
    CPU_PROFILER_ANY_TIME_MAIN_THREAD = 1 << 17,
    CPU_PROFILER_ANY_TIME_WORKER_THREAD = 1 << 18,
    ENABLE_HEAP_VERIFY = 1 << 19,
    ENABLE_MICROJOB_TRACE = 1 << 20,
    // Use DISABLE to adapt to the exsiting ArkProperties in testing scripts.
    DISABLE_SHARED_CONCURRENT_MARK = 1 << 22,
    ENABLE_ESM_TRACE = 1 << 24,
    ENABLE_MODULE_LOG = 1 << 25,
    ENABLE_SERIALIZATION_TIMEOUT_CHECK = 1 << 26,
    ENABLE_PAGETAG_THREAD_ID = 1 << 27,
    ENABLE_LOCAL_HANDLE_LEAK_DETECT = 1 << 28,`;
        const parsedOptions = TEXT_OPTIONS.split('\n').map(e => {
            const result = e.match(/([A-Z_]+?) = (.+?),/);
            if (result != null) {
                return [result[1], result[2]];
            }
            return null;
        });

        for (let i = 0; i < parsedOptions.length; i++) {
            const v = parsedOptions[i];

            if (v === null) {
                parsedOptions.splice(i, 1);
                i--;
                continue;
            }
            if (v[1].indexOf('<') > 0) {
                const ret = v[1].match(/(\d+) << (\d+)/);
                if (ret === null) {
                    continue;
                }
                v[1] = BigInt(ret[1]) << BigInt(ret[2])
            } else {
                v[1] = BigInt(v[1]);
            }
        }

        const selectorPanel = document.querySelector('#app>.selector')
        for (let opt of parsedOptions) {
            if (opt[1] === -1n) {
                continue;
            }
            const div = document.createElement('div');
            const e = document.createElement('input');
            e.id = opt[0].toLowerCase().replace(/_/g, '-');
            e.type = 'checkbox';
            e.data = opt[1].toString();
            if ((opt[1] & arkOptions) != 0n) {
                e.checked = true;
            }
            const l = document.createElement('label');
            l.setAttribute('for', e.id);
            l.textContent = opt[0].replace(/_/g, ' ').toLowerCase();
            div.append(e);
            div.append(l);
            selectorPanel.append(div);
        }

        const commandText = document.querySelector('#app .command');
        const generatorCommand = (options) => {
            return SET_PARAM_COMMAND + '0x' + options.toString(16);
        }
        commandText.value = generatorCommand(arkOptions);
        selectorPanel.addEventListener('change', (e) => {
            const i = e.target;
            const opt = BigInt(i.data);
            if (i.checked) {
                arkOptions = arkOptions | opt;
            } else {
                const deactivate = full64 - opt;
                arkOptions = arkOptions & deactivate;
            }
            commandText.value = generatorCommand(arkOptions);
        });

        const applyOptions = (option) => {
            const opts = document.querySelectorAll('#app>.selector input');
            for (let opt of opts) {
                opt.checked = (option & BigInt(opt.data)) != 0n;
            }
            commandText.value = generatorCommand(option);
        };

        document.querySelector('#app>.actions>.select-all').addEventListener('click', () => {
            const opts = document.querySelectorAll('#app>.selector input');
            for (let opt of opts) {
                arkOptions = arkOptions | BigInt(opt.data);
            }
            applyOptions(arkOptions);
        });

        document.querySelector('#app>.actions>.inverse').addEventListener('click', () => {
            const opts = document.querySelectorAll('#app>.selector input');
            for (let opt of opts) {
                opt.checked = !opt.checked;
                opt.dispatchEvent(new Event('change', { bubbles: true }));
            }
        });
        document.querySelector('#app>.actions>.reset').addEventListener('click', () => {
            arkOptions = DEFAULT_ARK_OPTIONS;
            applyOptions(DEFAULT_ARK_OPTIONS);
        });

        applyOptions(DEFAULT_ARK_OPTIONS);
    </script>
</body>

</html>